package jmine.tec.utils.cripto.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.TitledBorder;

import jmine.tec.utils.cripto.TokenUtil;

public class CriptoUI extends JFrame {

    private JTextField saltTextArea;

    private JTextField publicKeyTextArea;

    private JTextField privateKeyTextArea;

    private JTextArea sourceTextArea;

    private JTextArea destTextArea;

    public CriptoUI() {
        this.setTitle("Cripto UI");
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        this.initUI();
        this.setLocationRelativeTo(null);
    }

    private void initUI() {
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        this.getContentPane().add(mainPanel);

        mainPanel.add(this.createGenerateKeysPanel(), BorderLayout.NORTH);
        mainPanel.add(this.createEncodeDecodePanel(), BorderLayout.CENTER);
        this.pack();
    }

    private JPanel createGenerateKeysPanel() {
        JPanel panel = new JPanel();

        panel.setLayout(new BorderLayout());
        panel.setBorder(new TitledBorder("keys"));

        JPanel saltPanel = new JPanel();
        saltPanel.setLayout(new BorderLayout());
        JLabel saltLabel = new JLabel("Salt");
        saltPanel.add(saltLabel, BorderLayout.NORTH);
        this.saltTextArea = new JTextField();
        this.saltTextArea.setText("anything random");
        saltPanel.add(this.saltTextArea, BorderLayout.CENTER);

        JPanel publicPanel = new JPanel();
        publicPanel.setLayout(new BorderLayout());
        JLabel publicKeyLabel = new JLabel("public Key");
        publicPanel.add(publicKeyLabel, BorderLayout.NORTH);
        this.publicKeyTextArea = new JTextField();
        this.publicKeyTextArea.setText("public.key");
        publicPanel.add(this.publicKeyTextArea, BorderLayout.CENTER);

        final JButton choosePublicButton = new JButton(UIManager.getIcon("FileView.fileIcon"));
        choosePublicButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser = new JFileChooser();
                int returnVal = chooser.showOpenDialog(choosePublicButton);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    CriptoUI.this.publicKeyTextArea.setText(chooser.getSelectedFile().getAbsolutePath());
                }
            }
        });
        publicPanel.add(choosePublicButton, BorderLayout.EAST);

        JPanel privatePanel = new JPanel();
        privatePanel.setLayout(new BorderLayout());
        JLabel privateKeyLabel = new JLabel("private Key");
        privatePanel.add(privateKeyLabel, BorderLayout.NORTH);
        this.privateKeyTextArea = new JTextField();
        this.privateKeyTextArea.setText("private.key");
        privatePanel.add(this.privateKeyTextArea, BorderLayout.CENTER);

        final JButton choosePrivateButton = new JButton(UIManager.getIcon("FileView.fileIcon"));
        choosePrivateButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser = new JFileChooser();
                int returnVal = chooser.showOpenDialog(choosePrivateButton);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    CriptoUI.this.privateKeyTextArea.setText(chooser.getSelectedFile().getAbsolutePath());
                }
            }
        });
        privatePanel.add(choosePrivateButton, BorderLayout.EAST);

        JButton generateKeysButton = new JButton("generate new key pair");
        generateKeysButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                String publicKeyFile = CriptoUI.this.publicKeyTextArea.getText();
                String privateKeyFile = CriptoUI.this.privateKeyTextArea.getText();
                String salt = CriptoUI.this.saltTextArea.getText();
                TokenUtil.geraChaves(privateKeyFile, publicKeyFile, salt);
            }
        });

        JPanel keysPanel = new JPanel();
        keysPanel.setLayout(new BoxLayout(keysPanel, BoxLayout.X_AXIS));
        keysPanel.add(saltPanel);
        keysPanel.add(Box.createRigidArea(new Dimension(5, 0)));
        keysPanel.add(publicPanel);
        keysPanel.add(Box.createRigidArea(new Dimension(5, 0)));
        keysPanel.add(privatePanel);

        panel.add(keysPanel, BorderLayout.CENTER);
        panel.add(generateKeysButton, BorderLayout.SOUTH);

        return panel;
    }

    private JPanel createEncodeDecodePanel() {
        JPanel panel = new JPanel();

        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setBorder(new TitledBorder("encode / decode"));

        JPanel sourcePanel = new JPanel();
        sourcePanel.setLayout(new BorderLayout());
        this.sourceTextArea = new JTextArea();
        this.sourceTextArea.setPreferredSize(new Dimension(600, 200));
        JScrollPane sourceScroll = new JScrollPane(this.sourceTextArea);
        sourcePanel.add(sourceScroll, BorderLayout.CENTER);

        JPanel buttonsPanel = new JPanel();
        buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));

        JButton encodeButton = new JButton("encode with public key");
        encodeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                try {
                    String publicKey = CriptoUI.this.publicKeyTextArea.getText();
                    String data = CriptoUI.this.sourceTextArea.getText();
                    String cript = TokenUtil.encripta(publicKey, data);
                    CriptoUI.this.destTextArea.setText(cript);
                } catch (Throwable e) {
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(CriptoUI.this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }
            }
        });
        buttonsPanel.add(encodeButton);

        JButton decodeButton = new JButton("decode with private key");
        decodeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                try {
                    String privateKey = CriptoUI.this.privateKeyTextArea.getText();
                    String data = CriptoUI.this.sourceTextArea.getText();
                    String cript = TokenUtil.decripta(privateKey, data);
                    CriptoUI.this.destTextArea.setText(cript);
                } catch (Throwable e) {
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(CriptoUI.this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }
            }
        });
        buttonsPanel.add(decodeButton);

        sourcePanel.add(buttonsPanel, BorderLayout.SOUTH);

        this.destTextArea = new JTextArea();
        this.destTextArea.setPreferredSize(new Dimension(600, 200));
        this.destTextArea.setEditable(false);
        JScrollPane destScroll = new JScrollPane(this.destTextArea);

        panel.add(sourcePanel);
        panel.add(destScroll);

        return panel;
    }

    public static void main(String args[]) {
        if (!defineLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel")) {
            defineLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                CriptoUI frame = new CriptoUI();
                frame.setVisible(true);
            }
        });
    }

    /**
     * Tenta definir o look and feel dado, caso sucesso retorna true, false caso contrário
     * 
     * @param lookAndFeel lookAndFeel
     * @return boolean
     */
    private static boolean defineLookAndFeel(String lookAndFeel) {
        try {
            UIManager.setLookAndFeel(lookAndFeel);
            return true;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (InstantiationException e) {
            e.printStackTrace();
            return false;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return false;
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
            return false;
        }
    }
}
